﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

public class TLPlayer
{
    public TLPlayer(string id, System.Action callback = null)
    {
        timelineID = id;
        completeCallback = callback;
        isStart = false;
        //IsDestroy = false;
    }

    public string timelineID;
    private System.Action completeCallback;
    private bool isStart;
    
    public PlayableDirector director
    {
        get;
        private set;
    }
    public bool IsPlaying
    {
        get
        {
            return director == null ? false : isStart && director.time > 0 && director.state == PlayState.Playing;
        }
    }

    public bool isDestroy
    {
        get;
        private set;
    }

    public void OnUpdate()
    {
        if (director == null)
            return;

        if (isStart && director.time == 0 && director.state == PlayState.Paused)
        {
            isStart = false;
            if (completeCallback != null)
                completeCallback();
        }
    }

    // playPercent 0 - 1
    public void Play(float playPercent)
    {
        PlayableAsset playableAsset = FTimelineTool.LoadPlayableAsset(timelineID);
        FTimelineInfo data = FTimelineTool.LoadTimelineInfo(timelineID);
        if (playableAsset == null || data == null)
        {
            Debug.Log("---------------  Play timeline error! TimelineID:" + timelineID);
            return;
        }
        director = CreateDirector(timelineID);
        FTimelineTool.SetPlayableDirector(director, playableAsset, data);
        Camera[] arr = director.GetComponentsInChildren<Camera>(true);
        foreach (Camera cam in arr)
        {
            RaycastHolder raycastHolder = cam.gameObject.AddComponentEx<RaycastHolder>();
            raycastHolder.Initialize(timelineID);
        }
        director.initialTime = playPercent * director.duration;
        director.Play();
        isStart = true;
    }
    public void Pause()
    {
        if (director != null)
        {
            director.Pause();
        }
    }
    public void PauseAndStopAnimator()
    {
        if (director != null)
        {
            director.Pause();
            Animator[] arr = director.GetComponentsInChildren<Animator>();
            foreach (Animator anim in arr)
            {
                anim.enabled = false;
            }
        }
    }
    public void Resume()
    {
        if (director != null)
        {
            director.Resume();
        }
    }

    public void Dispose()
    {
        if (director != null)
        {
            GameObject.Destroy(director.gameObject);
            director = null;
        }
        //isDestroy = true;
    }

    private PlayableDirector CreateDirector(string timelineID)
    {
        PlayableDirector director = new GameObject("Timeline:" + timelineID).AddComponentEx<PlayableDirector>();
        return director;
    }
}






public class TimelinePlayer : MonoSingleton<TimelinePlayer>
{

    //private Dictionary<string, FTimelineInfo> timelineInfoDict = new Dictionary<string, FTimelineInfo>();
    private Dictionary<string, TLPlayer> playDict = new Dictionary<string, TLPlayer>();
    

    void Start()
    {
        //Play("10001", () =>
        //{
        //    Debug.LogError("6666666666");
        //});
    }

    private void Update()
    {
        if (playDict != null && playDict.Count > 0)
        {
            foreach (TLPlayer player in playDict.Values)
            {
                player.OnUpdate();
            }
        }
    }

    public void Play(string timelineID, System.Action callback = null)
    {
        if (string.IsNullOrEmpty(timelineID))
            return;
        if (playDict.ContainsKey(timelineID))
            return;

        TLPlayer player = new TLPlayer(timelineID, callback);
        player.Play(0);
        playDict.Add(timelineID, player);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="timelineID"></param>
    /// <param name="playPercent">0 - 1</param>
    /// <param name="callback"></param>
    public void Play(string timelineID, float playPercent, System.Action callback = null)
    {
        if (string.IsNullOrEmpty(timelineID))
            return;
        if (playDict.ContainsKey(timelineID))
            return;

        TLPlayer player = new TLPlayer(timelineID, callback);
        player.Play(playPercent);
        playDict.Add(timelineID, player);
    }

    public void Pause(string timelineID)
    {
        if (playDict.ContainsKey(timelineID))
            playDict[timelineID].Pause();
    }

    public void PauseAndStopAnimator(string timelineID)
    {
        if (playDict.ContainsKey(timelineID))
            playDict[timelineID].PauseAndStopAnimator();
    }

    public void Resume(string timelineID)
    {
        if (playDict.ContainsKey(timelineID))
            playDict[timelineID].Resume();
    }

    public void Remove(string timelineID)
    {
        //Debug.LogError(" --------------Remove:" + timelineID);

        if (playDict.ContainsKey(timelineID))
        {
            TLPlayer player = playDict[timelineID];
            playDict.Remove(timelineID);
            player.Dispose();
        }
    }

    public PlayableDirector GetDirector(string timelineID)
    {
        if (playDict.ContainsKey(timelineID))
            return playDict[timelineID].director;
        return null;
    }

    public bool IsPlaying(string timelineID)
    {
        return playDict.ContainsKey(timelineID) ? playDict[timelineID].IsPlaying : false;
    }

    public bool IsRuning(string timelineID)
    {
        return playDict.ContainsKey(timelineID) ? true : false;
    }

    public void DisposeAllTimeline()
    {
        if (playDict != null)
        {
            foreach (TLPlayer player in playDict.Values)
            {
                player.Dispose();
            }
            playDict.Clear();
        }
    }

    protected override void OnDestroy()
    {
        base.OnDestroy();

        DisposeAllTimeline();
    }

}
